package com.basker.pisces.domain.command.run;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.basker.pisces.domain.command.CommandExecuteContext;
import com.basker.pisces.domain.command.meta.Command;
import com.basker.pisces.domain.command.option.CommandExecuteOption;
import com.basker.pisces.domain.entity.meta.Entity;
import com.basker.pisces.spring.SpringApplicationContext;

/**
 * 命令运行器工厂
 *
 * @author hangwen
 */
class CommandRunnerFactory {

    public static CommandRunner<?> createRunner(Entity entity, Command command, CommandExecuteOption option) {
        CommandExecuteContext context = createContext(entity, command, option);
        CommandRunner<?> runner = createRunner(context);

        return runner;
    }

    private static CommandExecuteContext createContext(Entity entity, Command command, CommandExecuteOption option) {
        CommandExecuteContext context = new CommandExecuteContext();

        context.setEntity(entity);
        context.setCommand(command);
        context.setOption(option);

        return context;
    }

    private static CommandRunner<?> createRunner(CommandExecuteContext context) {
        String runnerName = context.getCommand().getRunnerBeanName();
        Assert.hasText(runnerName, "parameter 'command' has no runnerName");

        CommandRunner<?> runner = SpringApplicationContext.getInstance().getBean(runnerName, CommandRunner.class);

        runner.setContext(context);
        runner.initial();

        Entity resolvedEntity = resolveEntity(context, runner);
        context.setEntity(resolvedEntity);

        return runner;
    }

    private static Entity resolveEntity(CommandExecuteContext context, CommandRunner<?> runner) {
        Entity entity = context.getEntity();
        Command command = context.getCommand();

        if (command.getRequireFullEntity()) {
            Assert.isTrue(!entity.isSubEntity(), "command '" + command.getClass().getName() + "' require full entity");
            return entity;
        }

        /**
         * 执行命令获取需要加载的字段
         */
        List<String> requiedProprerties = runner.getRequiedProprertyAlias();
        if (CollectionUtils.isEmpty(requiedProprerties)) {
            return entity;
        }

        return entity.getSubEntity(new ArrayList<>(new LinkedHashSet<>(requiedProprerties)));
    }

}
